package com.jason.rxjavatest;

import android.annotation.TargetApi;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.support.annotation.NonNull;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.ImageView;
import android.widget.Toast;

import com.jason.rxjavatest.bean.Course;
import com.jason.rxjavatest.bean.Student;
import com.jason.rxjavatest.newtest.RxJavaNewTest001;

import java.util.ArrayList;
import java.util.List;

import rx.Observable;
import rx.Observer;
import rx.Subscriber;
import rx.android.schedulers.AndroidSchedulers;
import rx.functions.Action0;
import rx.functions.Action1;
import rx.functions.Func1;
import rx.schedulers.Schedulers;

public class MainActivity extends AppCompatActivity {


    private static final String TAG = MainActivity.class.getSimpleName();
    private rx.Observable observable;
    private Observer<String> observer;
    private ImageView iv;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        iv = (ImageView) findViewById(R.id.iv);

        findViewById(R.id.bt_main).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent(MainActivity.this, RxJavaTest1.class);
                startActivity(intent);
            }
        });

        findViewById(R.id.bt_new).setOnClickListener(v ->
                startActivity(new Intent(MainActivity.this, RxJavaNewTest001.class)));


        // 观察者
        observer = new Observer<String>() {
            @Override
            public void onCompleted() {
                Log.d(TAG, "Completed");
            }

            @Override
            public void onError(Throwable e) {
                Log.d(TAG, "Error!");

            }

            @Override
            public void onNext(String s) {
                Log.d(TAG, "Item:   " + s);
            }
        };

        // 观察者
        Subscriber<String> subscriber = new Subscriber<String>() {
            @Override
            public void onCompleted() {
                Log.e(TAG, "Completed--->");
            }

            @Override
            public void onError(Throwable e) {
                Log.e(TAG, "onError--->");
            }

            @Override
            public void onNext(String s) {

                Log.e(TAG, "Item--->" + s);

            }

            @Override
            public void onStart() {
                Log.e(TAG, "onStart--->");
            }
        };


        // 被观察者创建
        observable = rx.Observable.create(new rx.Observable.OnSubscribe<String>() {
            @Override
            public void call(Subscriber<? super String> subscriber) {

                subscriber.onNext("Hello");
                subscriber.onNext("Hi");
                subscriber.onNext("Rx");
                subscriber.onNext("Java");
                subscriber.onCompleted();

            }
        });

        /*
           与上面的create方法是等价的
        rx.Observable observable1 = rx.Observable.just("nihao", "zaijian");
        String[] words = {"你好", "数组"};
        rx.Observable observable2 = rx.Observable.from(words);
        */


        // 订阅
        //observable.subscribe(observer);
        //observable.subscribe(subscriber);

        //customAction();
        //printArrOrder();
        //setDrawableRes();

        //useObserveOn();
        //loadingDrawable();

        //printStuNameMapFunc();
        //printStuClassMap();
        printStuNameCourseFlatMap();

        useLiftMethod();

    }

    /**
     * 自定义事件
     */
    private void customAction() {

        Action1<String> onNextAction = new Action1<String>() {
            @Override
            public void call(String s) {

                Log.d(TAG + "  onNextAction", s);

            }
        };

        Action1<Throwable> onErrorAction = new Action1<Throwable>() {
            @Override
            public void call(Throwable throwable) {


            }
        };

        Action0 onCompletedAction = new Action0() {
            @Override
            public void call() {

                Log.d(TAG + "  onCompletedAction", "   onCompletedAction");

            }
        };


        // 自动创建Subscriber,并使用onNextAction来定义onNext()
        //observable.subscribe(onNextAction);

        // 自动创建Subscriber,并使用onNextAction和onErrorAction来定义onNext和onError
        //observable.subscribe(onNextAction, onErrorAction);

        // 自动创建Subscriber,并使用onNextAction、onErrorAction和onCompleteAction来定义onNext、onError和onComplete
        observable.subscribe(onNextAction, onErrorAction, onCompletedAction);


        /**
         简单解释一下这段代码中出现的 Action1 和 Action0。Action0 是 RxJava 的一个接口，它只有一个方法 call ()，这个方法是无参无返回值的；
         由于 onCompleted () 方法也是无参无返回值的，因此 Action0 可以被当成一个包装对象，将 onCompleted ()
         的内容打包起来将自己作为一个参数传入 subscribe () 以实现不完整定义的回调。这样其实也可以看做将 onCompleted () 方法作为参数传进了 subscribe
         ()，相当于其他某些语言中的『闭包』。Action1 也是一个接口，它同样只有一个方法 call (T param)，这个方法也无返回值，但有一个参数；与 Action0 同理，
         由于 onNext (T obj)和 onError (Throwable error)也是单参数无返回值的，因此 Action1 可以将 onNext (obj) 和
         onError(error) 打包起来传入 subscribe () 以实现不完整定义的回调。事实上，虽然 Action0 和 Action1 在 API 中使用最广泛，
         但 RxJava 是提供了多个 ActionX 形式的接口(例如 Action2, Action3) 的，它们可以被用以包装不同的无返回值的方法。

         */


    }

    /**
     * 按顺序打印字符串数组
     */
    private void printArrOrder() {

        String[] name = {"张三", "李四", "王五", "小二"};
        rx.Observable.from(name)
                .subscribe(new Action1<String>() {
                    @Override
                    public void call(String s) {
                        Log.e(TAG + "-----printArrOrder---", s);

                    }
                });
    }

    private void setDrawableRes() {

        Integer[] intArr = {R.mipmap.pig_01_3x,
                R.mipmap.pig_02_3x,
                R.mipmap.pig_03_3x,
                R.mipmap.pig_04_3x,
                R.mipmap.pig_05_3x,
                R.mipmap.pig_06_3x,
                R.mipmap.pig_07_3x,
                R.mipmap.pig_08_3x,
                R.mipmap.pig_09_3x,

        };

        rx.Observable.from(intArr)
                .subscribe(new Subscriber<Integer>() {
                    @Override
                    public void onCompleted() {

                    }

                    @Override
                    public void onError(Throwable e) {
                        Toast.makeText(getApplicationContext(), "Error!", Toast.LENGTH_SHORT).show();
                    }

                    @Override
                    public void onNext(Integer integer) {
                        try {
                            Thread.sleep(500);
                            Log.e(TAG, "睡500毫秒");
                            iv.setImageResource(integer);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }

                    }
                });


    }


    /*************************** Schedulers的使用 ********************************************/

    /**
     * 线程控制调度器的简单使用
     * 1. subscribeOn 订阅的事件在其他线程调用
     * 2. observeOn   事件的回调在主线程中调用
     */
    private void useObserveOn() {
        rx.Observable.just(1, 2, 3, 4)
                .subscribeOn(Schedulers.io()) // 指定subscribe()发生在io线程  事件消费在其他线程
                .observeOn(AndroidSchedulers.mainThread()) // 指定Subscriber 的回调发生在主线程
                .subscribe(new Action1<Integer>() {
                    @Override
                    public void call(Integer integer) {
                        // 调用obsererOn  则打印方法是在main主线程调用  如果注释掉则是在子线程打印
                        Log.e(TAG + "    observeOnUse--->", integer + "  thread---name---->" + Thread.currentThread().getName());

                    }
                });

    }


    private void loadingDrawable() {
        final int drawbleRes = R.mipmap.pig_04_3x;

        rx.Observable.create(new rx.Observable.OnSubscribe<Drawable>() {
            @TargetApi(Build.VERSION_CODES.LOLLIPOP)
            @Override
            public void call(Subscriber<? super Drawable> subscriber) {
                Drawable drawable = getTheme().getDrawable(drawbleRes);
                subscriber.onNext(drawable);
                subscriber.onCompleted();
            }
        })
                .subscribeOn(Schedulers.io()) // 指定subscribe()发生在IO线程
                .observeOn(AndroidSchedulers.mainThread()) // 指定Subscribe 回调发生在主线程
                .subscribe(new Observer<Drawable>() {

                    @Override
                    public void onCompleted() {

                    }

                    @Override
                    public void onError(Throwable e) {
                        Toast.makeText(MainActivity.this, "Error!", Toast.LENGTH_SHORT).show();
                    }

                    @Override
                    public void onNext(Drawable drawable) {
                        iv.setImageDrawable(drawable);
                    }
                });

    }


    /****
     * map fun1的使用
     ***/
    private void useMapFunc1() {

        rx.Observable.just("images/logo.png") // 输入类型 string
                .map(new Func1<String, Bitmap>() {

                    @Override
                    public Bitmap call(String filePath) { // 参数类型 Stirng

                        return null;     // 返回类型Bitmap
                    }
                })
                .subscribe(new Action1<Bitmap>() {
                    @Override
                    public void call(Bitmap bitmap) {  // 参数类型bitmap


                    }
                });

    }

    /**
     * 假设有一个数据结构『学生』，现在需要打印出一组学生的名字。实现方式很简单
     */
    private void printStuNameMapFunc() {

        Student[] students = {
                new Student("one", 1),
                new Student("two", 2),
                new Student("three", 3),
                new Student("four", 4),
                new Student("five", 5),
                new Student("six", 6),
                new Student("seven", 7),
                new Student("eight", 8),
                new Student("nine", 9),

        };

        Subscriber<String> subscriber = new Subscriber<String>() {
            @Override
            public void onCompleted() {

            }

            @Override
            public void onError(Throwable e) {

            }

            @Override
            public void onNext(String s) {
                Log.d(TAG, "printStuNameMapFunc------name-->" + s);
            }
        };

        rx.Observable.from(students)
                .map(new Func1<Student, String>() {
                    @Override
                    public String call(Student student) {
                        return student.name;
                    }
                })
                .subscribe(subscriber);
    }

    /**
     * 如果要打印出每个学生所需要修的所有课程的名称呢？（需求的区别在于，每个学生只有一个名字，但却有多个课程。）首先可以这样实现：
     */
    private void printStuClassMap() {

        Student[] students = getStudents();


        Subscriber<Student> subscriber = new Subscriber<Student>() {
            @Override
            public void onCompleted() {

            }

            @Override
            public void onError(Throwable e) {

            }

            @Override
            public void onNext(Student student) {
                List<Course> courses = student.list;

                for (int i = 0; i < courses.size(); i++) {
                    Course course = courses.get(i);
                    Log.d(TAG, "course.name----->" + course.name);
                }


            }
        };

        rx.Observable.from(students).subscribe(subscriber);

    }

    @NonNull
    private Student[] getStudents() {
        List<Course> list = new ArrayList<>();
        list.add(new Course("语文"));
        Student student1 = new Student("one", 1, list);

        list.add(new Course("数学"));
        Student student2 = new Student("two", 2);

        list.add(new Course("外语"));
        Student student3 = new Student("three", 3);

        list.add(new Course("物理"));
        Student student4 = new Student("four", 4);

        list.add(new Course("历史"));
        Student student5 = new Student("five", 5);

        list.add(new Course("地理"));
        Student student6 = new Student("six", 6);

        list.add(new Course("体育"));
        Student student7 = new Student("seven", 7);

        list.add(new Course("生物"));
        Student student8 = new Student("eight", 8);

        list.add(new Course("化学"));
        list.add(new Course("美术"));
        list.add(new Course("思想"));
        Student student9 = new Student("nine", 9);


        return new Student[]{
                student1,
                student2,
                student3,
                student4,
                student5,
                student6,
                student7,
                student8,
                student9,
        };
    }

    /**
     * 依然很简单。那么如果我不想在 Subscriber 中使用 for 循环，
     * 而是希望 Subscriber 中直接传入单个的 Course 对象呢（这对于代码复用很重要）？用 map() 显然是不行的，
     * 因为 map() 是一对一的转化，而我现在的要求是一对多的转化。
     * 那怎么才能把一个 Student 转化成多个 Course 呢？
     */
    private void printStuNameCourseFlatMap() {

        Student[] students = getStudents();

        Subscriber<Course> subscriber = new Subscriber<Course>() {
            @Override
            public void onCompleted() {

            }

            @Override
            public void onError(Throwable e) {

            }

            @Override
            public void onNext(Course course) {
                Log.d(TAG, "course-----name---->" + course.name);

            }
        };

        Observable.from(students)
                .flatMap(new Func1<Student, Observable<Course>>() {
                    @Override
                    public Observable<Course> call(Student student) {
                        return Observable.from(student.list);
                    }

                })
                .subscribe(subscriber);



    }

    /**
     * Operator的实现
     */
    private void useLiftMethod() {

        Observable<Integer> observable = Observable.just(1, 2, 3, 4);


        observable.lift(new Observable.Operator<String, Integer>() {

            @Override
            public Subscriber<? super Integer> call(final Subscriber<? super String> subscriber) {
                return new Subscriber<Integer>() {
                    @Override
                    public void onCompleted() {
                        subscriber.onCompleted();
                    }

                    @Override
                    public void onError(Throwable e) {
                        subscriber.onError(e);
                    }

                    @Override
                    public void onNext(Integer integer) {
                        subscriber.onNext("integer------->" + integer);

                    }
                };
            }
        });





    }


}
